package com.taxshare.seller.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.taxshare.freemark.utils.FreemarkUtil;
import com.taxshare.mybatis.pager.PageHelp;
import com.taxshare.mybatis.pager.PageRequest;
import com.taxshare.response.beans.Response;
import com.taxshare.seller.constant.CodeConstant;
import com.taxshare.seller.constant.ResultConstant;
import com.taxshare.seller.entity.*;
import com.taxshare.seller.mapper.InvoiceDetailMapper;
import com.taxshare.seller.mapper.InvoicedMapper;
import com.taxshare.seller.remote.ApiClientService;
import com.taxshare.seller.service.sst.IntJsonUtil;
import com.taxshare.seller.util.InvoiceHelper;
import com.taxshare.seller.util.MwDecryptUtil;
import com.taxshare.seller.util.Xml2Map;
import com.taxshare.seller.view.dto.*;
import com.taxshare.tools.constant.CommonConstant;
import com.taxshare.tools.token.UserInfoUtil;
import com.taxshare.tools.util.DateUtil;
import com.taxshare.tools.util.StringUtil;
import com.taxshare.tools.util.UUIDUitl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liupp
 * @ClassName: OpenInvoiceService
 * @Description: (待开发票)
 * @date 2021年4月8日
 */
@Service
//@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
@Slf4j
public class OpenInvoiceService extends ServiceImpl<InvoicedMapper, SellerInvoiceEntity> {

    @Autowired
    InvoiceDetailMapper invoiceDetailMapper;

    @Autowired
    ApiClientService apiClientService;

    @Autowired
    StockDetailService stockDetailService;

    @Autowired
    EquipmentService equipmentService;

    @Autowired
    AlsCancelLogService aslCancelLogService;

    @Autowired
    AlsCancelDetailLogService alsCancelDetailLogService;

    @Value("${zzsfp.url}")
    private String zzsfpUrl;

    @Autowired
    CommService commService;

    @Autowired
    AsyncService asyncService;
    /**
     * 设备状态标识
     */
    public static final String OFFLINE_DISABLE = "0";
    public static final String OFFLINE = "离线";
    public static final String ONLINE_DISABLE = "1";
    public static final String ONLINE = "在线";
    public static final String STATUS = "未启用";

    /**
     * @param @param  query
     * @param @return 参数
     * @return Response 返回类型
     * @throws
     * @Title: dkInvoicedQuery
     * @Description: (待开发票列表)
     */
    public Response getSubDataByPage(PageRequest<InvoicedDTO> query) {
        QueryWrapper<SellerInvoiceEntity> queryWrapper = new QueryWrapper<>();
        InvoicedDTO invoicedDTO = query.getInfo();
        if (StrUtil.isNotBlank(invoicedDTO.getInvoiceType())) {
            queryWrapper.eq("invoice_type", invoicedDTO.getInvoiceType());//发票类型
        }
        if (StrUtil.isNotBlank(invoicedDTO.getMakeInvoiceType())) {
            queryWrapper.eq("make_invoice_type", invoicedDTO.getMakeInvoiceType());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getInvoiceCode())) {
            queryWrapper.eq("invoice_code", invoicedDTO.getOldInvoiceCode());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getInvoiceNo())) {
            queryWrapper.eq("invoice_no", invoicedDTO.getInvoiceNo());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getInvoiceState())) {
            queryWrapper.eq("invoice_state", invoicedDTO.getInvoiceState());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getOldInvoiceCode())) {
            queryWrapper.eq("old_invoice_code", invoicedDTO.getOldInvoiceNo());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getOldInvoiceNo())) {
            queryWrapper.eq("old_invoice_no", invoicedDTO.getOldInvoiceNo());
        }
        if (StrUtil.isNotBlank(invoicedDTO.getSellerName())) {
            queryWrapper.like("seller_name", invoicedDTO.getSellerName());//销方名称
        }
        if (StrUtil.isNotBlank(invoicedDTO.getSellerTaxNo())) {
            queryWrapper.eq("seller_tax_no", invoicedDTO.getSellerTaxNo());//销方税号
        } else {
            List<String> taxNos = commService.getTaxNumbers();
            queryWrapper.in("seller_tax_no", taxNos);//销方税号
        }
        if (StrUtil.isNotBlank(invoicedDTO.getPurchaserName())) {
            queryWrapper.like("purchaser_name", invoicedDTO.getPurchaserName());//购方名称
        }
        if (StrUtil.isNotBlank(invoicedDTO.getPurchaserTaxNo())) {
            queryWrapper.eq("purchaser_tax_no", invoicedDTO.getPurchaserTaxNo());//购方税号
        }
        if (StrUtil.isNotBlank(invoicedDTO.getDataSource())) {
            queryWrapper.eq("data_source", invoicedDTO.getDataSource());//数据来源
        }
        if (StrUtil.isNotBlank(invoicedDTO.getDrawer())) {
            queryWrapper.like("drawer", invoicedDTO.getDrawer());//开票人
        }
        if (StrUtil.isNotBlank(invoicedDTO.getMakeInvoiceState())) {
            queryWrapper.eq("make_invoice_state", invoicedDTO.getMakeInvoiceState());//开票状态
        } else {
            List<String> makeState = new ArrayList<>();
            makeState.add("0");
            makeState.add("1");
            makeState.add("3");
            queryWrapper.in("make_invoice_state", makeState);
        }
        if (StrUtil.isNotBlank(invoicedDTO.getDocId())) {
            queryWrapper.like("doc_id", invoicedDTO.getDocId());//结算单
        }

        if (StrUtil.isNotBlank(invoicedDTO.getInvoiceDateStart()) && StrUtil.isNotBlank(invoicedDTO.getInvoiceDateEnd())) {
            queryWrapper.between("invoice_date", invoicedDTO.getInvoiceDateStart(), invoicedDTO.getInvoiceDateEnd());
        }
        queryWrapper.orderByDesc("create_time");
        IPage<SellerInvoiceEntity> sellerInvoiceEntityIPage = PageHelp.siamplePage(this, queryWrapper, query.getPage(), SellerInvoiceEntity.class);
        return Response.success(sellerInvoiceEntityIPage);
    }

    /**
     * @param @param  sellerInvoiceDetailDTO
     * @param @return 参数
     * @return Response    返回类型
     * @throws
     * @Title: upInvoiceRemark
     * @Description: (根据发票流水号修改备注)
     */
    public Response upInvoiceRemark(SellerInvoiceDetailDTO sellerInvoiceDetailDTO) {
        SellerInvoiceEntity sellerInvoiceEntity = this.getById(sellerInvoiceDetailDTO.getSerialNo());
        sellerInvoiceEntity.setRemark(sellerInvoiceDetailDTO.getRemark());
        sellerInvoiceEntity.setUpdateTime(new Date());
        return Response.success(this.updateById(sellerInvoiceEntity));
    }

    /**
     * 批量开票
     *
     * @param uuids
     * @return
     */
    public Response synchroOpenInvoice(List<String> uuids) {
        Response res = new Response();
        String msg = "";
        //循环待开票数据（开票）
        log.info("++++++++++++++++++++++++++开始批量开票，请求流水号为：" + uuids.toString());
        if (uuids.isEmpty()) {
            return Response.error("SEL_107");
        }
        for (int i = 0; i < uuids.size(); i++) {
            String uuid = uuids.get(i);
            SellerInvoiceEntity sellerInvoice = this.getById(uuid);
            if (sellerInvoice == null) {
                res.setCode("SEL_107");
                msg += "第" + (i + 1) + "" + "张发票开具失败，错误原因：业务标志为空，请联系运维人员！";
                continue;
            }
            //获取开票设备 A9对应明源开票 其他则税神通开票
            String sellerTaxNo = sellerInvoice.getSellerTaxNo();
            EquipmentEntity equipmentEntity = equipmentService.getOne(new QueryWrapper<EquipmentEntity>().eq("seller_tax_no", sellerTaxNo).eq("disable", "1"));
            if (null == equipmentEntity) {
                msg += "发票开具失败，错误原因：该纳税人识别号对应的设备未添加或开启，请检查！";
                res.setMsg(msg);
                return res;
            }
            //设备类型
            String equipmentMode = equipmentEntity.getEquipmentMode();
            //查询开票明细信息
            QueryWrapper<SellerInvoiceDetailEntity> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("serial_no", sellerInvoice.getSerialNo());
            queryWrapper1.orderByAsc("invoice_sort");
            List<SellerInvoiceDetailEntity> invoiceDetailList = invoiceDetailMapper.selectList(queryWrapper1);
            //开票
            if (CodeConstant.A9.equals(equipmentMode)) {
                msg += synchroOpenInvoiceA9(sellerInvoice, invoiceDetailList, msg, i);
            } else {
                msg += synchroOpenInvoiceSST(equipmentEntity, sellerInvoice, invoiceDetailList, msg, i);
            }
        }
        if (StrUtil.isBlank(msg)) {
            if (1 == uuids.size()) {
                SellerInvoiceEntity sellerInvoice = this.getById(uuids.get(0));
                return Response.success(sellerInvoice);
            }
            return Response.success();
        }
        res.setMsg(msg);
        return res;
    }

    /**
     * A9服务器开票
     *
     * @param sellerInvoice
     * @param msg
     * @param i
     * @return
     */
    private String synchroOpenInvoiceA9(SellerInvoiceEntity sellerInvoice, List<SellerInvoiceDetailEntity> invoiceDetailList, String msg, int i) {
        String sellerTaxNo = sellerInvoice.getSellerTaxNo();
        String interfaceCode = "EI.FPKJ.U.EC.INTRA";
        String url = zzsfpUrl + "/fpkj/" + sellerTaxNo;
        String seriano = sellerInvoice.getSerialNo();
        String invoiceType = sellerInvoice.getInvoiceType();
        String fplx = InvoiceHelper.transFplxdm(invoiceType);
        String serialNo = sellerInvoice.getSerialNo();
        invoiceDetailList.forEach(iteam -> {
            if (StrUtil.isNotBlank(iteam.getTaxRateMark())) {
                switch (iteam.getTaxRateMark()) {
                    case "0":
                        iteam.setPreferentialMark("1");
                        break;
                    case "1":
                        iteam.setPreferentialMark("1");
                        iteam.setZzstsgl("免税");
                        break;
                    case "2":
                        iteam.setPreferentialMark("1");
                        iteam.setZzstsgl("不征税");
                        break;
                    case "3":
                        iteam.setPreferentialMark("0");
                        break;
                    default:
                        break;
                }
            }
        });
        sellerInvoice.setFplx(fplx);
        sellerInvoice.setInvoiceDetail(invoiceDetailList);
        //开票内容
        String makeInvoiceData = FreemarkUtil.getTemplateObj("/makeInvoice.ftl", sellerInvoice);
        //开票请求
        String xmlData = InvoiceHelper.getXmlData(makeInvoiceData, interfaceCode, sellerTaxNo, serialNo);
        if (StrUtil.isBlank(xmlData)) {
            msg += "第" + (i + 1) + "张发票开具失败，错误原因：该纳税人识别号匹配【开票分机号-终端号】失败，请检查！";
            return msg;
        }
        InterfaceDTO interfaceDTO = new InterfaceDTO();
        interfaceDTO.setXmlData(xmlData);
        interfaceDTO.setUrl(url);
        try {
            Response response = apiClientService.callSales(interfaceDTO);
            if (CodeConstant.T0000.equals(response.getCode())) {
                String reqcontent = response.getData().toString();
                Map resMap = Xml2Map.Xml2Mapz(reqcontent);
                try {
                    openElectricInvoice(resMap, sellerInvoice, invoiceType);
                } catch (Exception e) {
                    msg += "第" + (i + 1) + "" + "张发票开票成功，回写数据库或者回写明源失败";
                    return msg;
                }
            } else {
                msg += "第" + (i + 1) + "" + "张发票开具失败，错误原因：" + response.getMsg() + ",请至【待开发票管理】中查看，请勿重复开具。";
                return msg;
            }
        } catch (Exception e) {
            log.error("开票接口请求异常", e);
            updateRreason(seriano, "开票接口请求异常");
            msg += "第" + (i + 1) + "" + "张发票开具失败，,请至【待开发票管理】中查看，请勿重复开具。错误原因：" + "开票接口请求异常，请求流水号：" + seriano;
            return msg;
        }
        return msg;
    }


    /**
     * 税神通开票
     *
     * @param equipmentEntity
     * @param sellerInvoice
     * @param invoiceDetailList
     * @param msg
     * @param i
     * @return
     */
    private String synchroOpenInvoiceSST(EquipmentEntity equipmentEntity, SellerInvoiceEntity sellerInvoice, List<SellerInvoiceDetailEntity> invoiceDetailList, String msg, int i) {
        //拼接报文
        String json;
        if (("005".equals(sellerInvoice.getInvoiceType()))) {
            json = IntJsonUtil.carMakeInvoice(equipmentEntity.getAppid(), equipmentEntity.getEquipmentMode(), sellerInvoice, invoiceDetailList.get(0));
        } else {
            json = IntJsonUtil.makeInvoice(equipmentEntity.getAppid(), equipmentEntity.getEquipmentMode(), sellerInvoice, invoiceDetailList);
        }
        String invoiceType = sellerInvoice.getInvoiceType();
        String seriano = sellerInvoice.getSerialNo();
        int size = invoiceDetailList.size();
        if (size <= 8) {
            sellerInvoice.setListFlag(CodeConstant.COMM_CODE_0);
        } else {
            sellerInvoice.setListFlag(CodeConstant.COMM_CODE_1);
        }
        try {
            SellerInvoiceDTO sellerInvoiceDTO = new SellerInvoiceDTO();
            sellerInvoiceDTO.setBw(json);
            Response response = apiClientService.callSST(sellerInvoiceDTO);
            String result = (String) response.getData();
            JSONObject jsonObject = (JSONObject) JSON.parse(result);
            String code = jsonObject.getString("code");
            String msgFh = jsonObject.getString("msg");
            if (code.equals("00000")) {
                Map resMap = (Map) jsonObject.get("data");
                //开票成功回写数据
                openElectricInvoiceSST(resMap, sellerInvoice, invoiceType);
                //电票更新pdfUrl
                if ("026".equals(invoiceType)) {
                    asyncService.updatePdfUrl(resMap, sellerInvoice.getSellerTaxNo(), equipmentEntity.getAppid(), seriano);
                }
            } else {
                msg += "第" + (i + 1) + "" + "张发票开具失败 ，错误原因：" + msgFh + ",请至【待开发票管理】中查看，请勿重复开具。";
                return msg;
            }
        } catch (Exception e) {
            log.error("开票接口请求异常", e);
            updateRreason(seriano, "开票接口请求异常");
            msg += "第" + (i + 1) + "" + "张发票开具失败，,请至【待开发票管理】中查看。错误原因：" + "开票接口请求异常，请求流水号：" + seriano;
            return msg;
        }
        return msg;
    }

    public void updateRreason(String seriano, String msg) {
        QueryWrapper<SellerInvoiceEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("serial_no", seriano);
        SellerInvoiceEntity sellerInvoiceEntity = this.getOne(queryWrapper);
        sellerInvoiceEntity.setFailReason(msg);
        sellerInvoiceEntity.setMakeInvoiceState("0");
        sellerInvoiceEntity.setNowSid(UUIDUitl.UUID32(false));
        this.updateById(sellerInvoiceEntity);
    }

    /**
     * A9开票成功回写
     *
     * @param resMap
     * @param sellerInvoice
     * @param invoiceType
     * @return
     * @throws Exception
     */
    public Response openElectricInvoice(Map resMap, SellerInvoiceEntity sellerInvoice, String invoiceType) throws Exception {
        Response res = new Response();
        String skm = MapUtils.getString(resMap, "FWMW", "");
        String fpdm = MapUtils.getString(resMap, "FP_DM", "");
        String fphm = MapUtils.getString(resMap, "FP_HM", "");
        String kprq = DateUtil.getDatetoDay(MapUtils.getString(resMap, "KPRQ", ""));
        String ewm = MapUtils.getString(resMap, "EWM", "");
        sellerInvoice.setInvoiceCode(fpdm);
        sellerInvoice.setInvoiceNo(fphm);
        sellerInvoice.setInvoiceDate(kprq);
        if (StrUtil.isNotBlank(kprq)) {
            sellerInvoice.setInvoiceMonth(kprq.substring(0, 7));
        }
        sellerInvoice.setCheckCode(MapUtils.getString(resMap, "JYM", ""));
        sellerInvoice.setMakeInvoiceMode("5");
        sellerInvoice.setMakeInvoiceState("2");
        sellerInvoice.setCipherText(MwDecryptUtil.desMw(skm));
        sellerInvoice.setQrCode(MwDecryptUtil.desMw(ewm));//二维码未解密
        sellerInvoice.setInvoiceState("0");
        if (!StringUtil.isEmpty(kprq)) {
            String sjy = DateUtil.getDateto(MapUtils.getString(resMap, "KPRQ", ""));
            sellerInvoice.setInvoiceMonth(sjy);
            sellerInvoice.setInvoiceDay(kprq);
        }
        if ("026".equals(invoiceType)) {
            getUrlPDF(sellerInvoice);
        }
        this.updateById(sellerInvoice);
        String docId = sellerInvoice.getDocId();
        //todo 发票开具成功回写信息给ALS

        //发票开具成功，回写发票信息给明源

        if (docId != null && "" != docId) {
            writeBackInvoiceData(sellerInvoice.getDocId());
        }
        res.setCode(CodeConstant.T0000);
        res.setMsg("开票成功");
        return res;
    }

    /**
     * 税神通开票成功回写
     *
     * @param resMap
     * @param sellerInvoice
     * @param invoiceType
     * @return
     * @throws Exception
     */
    private Response openElectricInvoiceSST(Map resMap, SellerInvoiceEntity sellerInvoice, String invoiceType) throws Exception {
        Response res = new Response();
        String skm = MapUtils.getString(resMap, "mw", "");
        String fpdm = MapUtils.getString(resMap, "fpdm", "");
        String fphm = MapUtils.getString(resMap, "fphm", "");
        String invoiceDate = MapUtils.getString(resMap, "kprq", "");
        String kprq = DateUtil.getDatetoDay(invoiceDate);
        sellerInvoice.setInvoiceCode(fpdm);
        sellerInvoice.setInvoiceNo(fphm);
        sellerInvoice.setInvoiceDate(kprq);
        sellerInvoice.setCheckCode(MapUtils.getString(resMap, "jym", ""));
        sellerInvoice.setMakeInvoiceMode("2");
        sellerInvoice.setMakeInvoiceState("2");
        sellerInvoice.setCipherText(skm);
        sellerInvoice.setInvoiceState("0");
        if (!StringUtil.isEmpty(invoiceDate)) {
//            String sjy = DateUtil.getDatetoDay(invoiceDate);
//            String sjt = DateUtil.getDatetoDay(invoiceDate);
            sellerInvoice.setInvoiceMonth(kprq.substring(0, 7));
            sellerInvoice.setInvoiceDay(kprq);
        }
        this.updateById(sellerInvoice);
//        //开具成功后判断是否达到剩余发票预警值，超过就推送消息
//        asyncService.sendInvoiceWarnMsg(sellerInvoice);
        return res;
    }


    /**
     * 电票发票地址
     *
     * @param sellerInvoice
     */
    private void getUrlPDF(SellerInvoiceEntity sellerInvoice) throws Exception {
        String url = zzsfpUrl + "fpqzInterface";
        String interfaceCode = "EI.KBFPZF.U.EC.INTRA";
        String fplx = InvoiceHelper.transFplxdm(sellerInvoice.getInvoiceType());
        String ykInvoiceData = FreemarkUtil.getTemplateObj("/getPDFurl.ftl", sellerInvoice);
        String xmlData = InvoiceHelper.getXmlData(ykInvoiceData, interfaceCode, sellerInvoice.getSellerTaxNo(), null);
        InterfaceDTO interfaceDTO = new InterfaceDTO();
        interfaceDTO.setXmlData(xmlData);
        interfaceDTO.setUrl(url);
        Response response = apiClientService.callSales(interfaceDTO);
        if ("0000".equals(response.getCode())) {
            String reqcontent = response.getMsg();
            Map resMap = Xml2Map.Xml2Mapz(reqcontent);
            Map RESPONSE_FPQZ = (Map) resMap.get("RESPONSE_FPQZ");
            String PDF_URL = RESPONSE_FPQZ.get("PDF_URL").toString();
            sellerInvoice.setInvoiceUrl(PDF_URL);
        }
    }

    /**
     * 回写发票号码、开具状态给明源
     */
    @Async
    public void writeBackInvoiceData(String docId) {
        WriteBackInvoiceDTO writeBackInvoiceDTO = new WriteBackInvoiceDTO();
        writeBackInvoiceDTO.setVouchGUID(docId);
        writeBackInvoiceDTO.setKey("HL");
        //明源单据发票信息
        List<SellerInvoiceEntity> sellerInvoiceEntities
                = baseMapper.selectList(new QueryWrapper<SellerInvoiceEntity>().eq("doc_id", docId));
        //明源单据预制的发票总数量
        int docInvoice = sellerInvoiceEntities.size();
        //已开发票的数量
        List<SellerInvoiceEntity> openeds
                = baseMapper.selectList(new QueryWrapper<SellerInvoiceEntity>().eq("doc_id", docId)
                .eq("make_invoice_state", "2"));
        //已开发票的数量
        int isMake = openeds.size();
        if (isMake == 0) {
            writeBackInvoiceDTO.setVatStatus(CodeConstant.WKJ);
        } else if (isMake > 0 && isMake < docInvoice) {
            writeBackInvoiceDTO.setVatStatus(CodeConstant.BFKJ);
        } else if (isMake > 0 && isMake == docInvoice) {
            writeBackInvoiceDTO.setVatStatus(CodeConstant.YKJ);
        }
        //返回订单全部发票号码并逗号分隔
        String invoiceNo = openeds.stream().map(t -> t.getInvoiceNo()).collect(Collectors.joining(","));
        writeBackInvoiceDTO.setVatNo(invoiceNo);
        apiClientService.writeBackIncoice(writeBackInvoiceDTO);
    }

    /**
     * 待开发票类型修改
     *
     * @param updateInvoiceTypeDTO
     * @return
     */
    public Response updateInvoiceType(UpdateInvoiceTypeDTO updateInvoiceTypeDTO) {
        UpdateWrapper<SellerInvoiceEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("uuid", updateInvoiceTypeDTO.getUuid())
                .set("invoice_type", updateInvoiceTypeDTO.getInvoiceType());
        boolean result = this.update(new SellerInvoiceEntity(), updateWrapper);
        if (result) {
            return Response.success();
        }
        return Response.error();
    }

    /**
     * 设备余票,状态查询
     *
     * @param sellerNo
     * @return
     */
    public Response queryStock(String sellerNo) {
        QueryWrapper<StockDetailEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("seller_tax_no", sellerNo);
        List<StockDetailEntity> list = stockDetailService.list(queryWrapper);
        HashMap<String, String> map = new HashMap<>(10);
        //初始化
        map.put("ZP", "0");
        map.put("PP", "0");
        map.put("DP", "0");
        list.forEach(item -> {
            if (CodeConstant.INVOICETYPE_ZP.equals(item.getInvoiceTypeNo())) {
                map.put("ZP", item.getInvoiceSheet());
            } else if (CodeConstant.INVOICETYPE_PP.equals(item.getInvoiceTypeNo())) {
                map.put("PP", item.getInvoiceSheet());
            } else {
                map.put("DP", item.getInvoiceSheet());
            }
        });
        //设备状态
        QueryWrapper<EquipmentEntity> queryEquipment = new QueryWrapper<>();
        queryEquipment.eq("seller_tax_no", sellerNo);
        EquipmentEntity one = equipmentService.getOne(queryEquipment);
        if (one != null) {
            if (OFFLINE_DISABLE.equals(one.getDisable())) {
                map.put("status", OFFLINE);
            } else if (ONLINE_DISABLE.equals(one.getDisable())) {
                map.put("status", ONLINE);
            }
        } else {
            map.put("status", STATUS);
        }
        return Response.success(map);
    }

    /**
     * 获取当前开票的发票代码和号码【余票同步】
     */
    public Response syncNextInvoice(InvoicedDTO invoiceDTO) throws Exception {
        Response response = null;
        EquipmentEntity equipmentEntity = equipmentService.queryEquipment(invoiceDTO.getSellerTaxNo());
        if (equipmentEntity == null || CodeConstant.COMM_CODE_0.equals(equipmentEntity.getDisable())) {
            return Response.error(CodeConstant.ERROR, "该税号下无设备或设备未启用，请启用后重试！");
        }
        if (CodeConstant.A9.equals(equipmentEntity.getEquipmentMode())) {
            response = nextInvoiceA9(invoiceDTO);
        } else {
            response = nextInvoiceSST(invoiceDTO, equipmentEntity);
        }
        return response;
    }

    public Response nextInvoiceA9(InvoicedDTO invoiceDTO) throws Exception {
        String url = zzsfpUrl + "busiInterface";
        String interfaceCode = "EI.HQZDPZDQDMHM.U.EC.INTRA";
        String fplx = InvoiceHelper.transFplxdm(invoiceDTO.getInvoiceType());
        invoiceDTO.setInvoiceType(fplx);
        String ykInvoiceData = FreemarkUtil.getTemplateObj("/standbyTicket.ftl", invoiceDTO);
        String xmlData = InvoiceHelper.getXmlData(ykInvoiceData, interfaceCode, invoiceDTO.getSellerTaxNo(), null);
        InterfaceDTO interfaceDTO = new InterfaceDTO();
        interfaceDTO.setXmlData(xmlData);
        interfaceDTO.setUrl(url);
        Response response = apiClientService.callSales(interfaceDTO);
        if (CommonConstant.SUCCESS.equals(response.getCode())) {
            Map<String, String> invoiceMap = new HashMap<>();
            Map resMap = Xml2Map.Xml2Mapz(response.getData().toString());
            invoiceMap.put("invoiceCode", MapUtil.getStr(resMap, "DQFPDM"));
            invoiceMap.put("invoiceNo", MapUtil.getStr(resMap, "DQFPHM"));
            return Response.success(invoiceMap);
        } else {
            return Response.error(ResultConstant.RET_S9999_CODE, response.getMsg());
        }
    }

    public Response nextInvoiceSST(InvoicedDTO invoiceDTO, EquipmentEntity equipmentEntity) throws Exception {
        Response responseData = new Response();
        SellerInvoiceEntity sellerInvoiceEntity = new SellerInvoiceEntity();
        sellerInvoiceEntity.setInvoiceType(invoiceDTO.getInvoiceType());
        sellerInvoiceEntity.setSellerTaxNo(invoiceDTO.getSellerTaxNo());
        String json = IntJsonUtil.getUserInvoiceNo(equipmentEntity.getEquipmentMode(), equipmentEntity.getAppid(), sellerInvoiceEntity);
        SellerInvoiceDTO sellerInvoiceDTO = new SellerInvoiceDTO();
        sellerInvoiceDTO.setBw(json);
        Response response = apiClientService.callSST(sellerInvoiceDTO);
        String result = (String) response.getData();
        JSONObject jsonObject = (JSONObject) JSON.parse(result);
        String code = jsonObject.getString("code");
        String msg = jsonObject.getString("msg");
        if (CodeConstant.THIRD_PARTY_SUCCESS.equals(code)) {
            Map resMap = (Map) jsonObject.get("data");
            responseData.setData(resMap);
            responseData.setCode(CodeConstant.T0000);
        } else {
            responseData.setCode(CodeConstant.T0001);
            responseData.setMsg("获取当前发票代码号码失败" + msg + "！");
        }
        return responseData;
    }

    /**
     * 发票驳回
     *
     * @param invoiceDTO
     * @return
     */
    public Response cancelInvoice(AlsCancelInvoiceDTO invoiceDTO) {
        QueryWrapper<SellerInvoiceEntity> queryInvoice = new QueryWrapper<>();
        queryInvoice.eq("order_no", invoiceDTO.getOrderNo());
        List<SellerInvoiceEntity> list = this.list(queryInvoice);
        try {
            try {
                if (list != null && list.size() != 0) {
                    //添加驳回日志,并删除待开发票
                    insertCancelLog(list, invoiceDTO.getCancelReason());
                    baseMapper.deleteBatchIds(list);
                }
            } catch (Exception e) {
                log.info("新增驳回日志失败，请重新操作！");
                return Response.error("本地驳回失败，请重新操作！");
            }
            //TODO 封装驳回数据返回给ALS

        } catch (Exception e) {
            log.info("驳回数据返回失败，请重新操作！");
            return Response.error("SEL_031");
        }
        return Response.success();
    }

    /**
     * 待开发票驳回日志
     *
     * @param list
     * @param reason
     */
    private void insertCancelLog(List<SellerInvoiceEntity> list, String reason) {
        ArrayList<AlsCancelLogEntity> cancelList = new ArrayList<>();
        list.forEach(item -> {
            AlsCancelLogEntity entity = new AlsCancelLogEntity();
            BeanUtil.copyProperties(item, entity);
            entity.setCancelReason(reason);
            cancelList.add(entity);
        });
        aslCancelLogService.saveBatch(cancelList);
        //添加驳回明细日志
        QueryWrapper<SellerInvoiceDetailEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("serial_no", list.get(0).getSerialNo());
        List<SellerInvoiceDetailEntity> detailList = invoiceDetailMapper.selectList(queryWrapper);
        ArrayList<AlsCancelDetailLogEntity> cancelDetailLogEntities = new ArrayList<>();
        if (detailList != null && detailList.size() != 0) {
            detailList.forEach(item -> {
                AlsCancelDetailLogEntity alsCancelDetailLogEntity = new AlsCancelDetailLogEntity();
                BeanUtil.copyProperties(item, alsCancelDetailLogEntity);
                cancelDetailLogEntities.add(alsCancelDetailLogEntity);
            });
            alsCancelDetailLogService.saveBatch(cancelDetailLogEntities);
            invoiceDetailMapper.deleteBatchIds(detailList);
        }
    }

    /**
     * 调接口获取pdfurl
     *
     * @param reqMap
     */
    public void CallUpdatePdfUrl(Map<String, String> reqMap) {
        String fpdm = MapUtils.getString(reqMap, "fpdm", "");
        String fphm = MapUtils.getString(reqMap, "fphm", "");
        String appid = MapUtils.getString(reqMap, "appid", "");
        String taxNo = MapUtils.getString(reqMap, "taxNo", "");
        String seriano = MapUtils.getString(reqMap, "seriano", "");
        System.out.println("调用PDF系统时间：" + DateUtil.getCurrent() + "  参数信息" + reqMap);
        //组装参数
        List<Map<String, String>> invoiceMaps = new ArrayList<>();
        Map<String, String> invoiceMap = new HashMap<>();
        invoiceMap.put("fpdm", fpdm);
        invoiceMap.put("fphm", fphm);
        invoiceMaps.add(invoiceMap);
        //更新电子发票url
        String json = IntJsonUtil.updatePdfUrl(appid, taxNo, invoiceMaps);
        SellerInvoiceDTO sellerInvoiceDTO = new SellerInvoiceDTO();
        sellerInvoiceDTO.setBw(json);
        Response response = apiClientService.callSST(sellerInvoiceDTO);
        String result = (String) response.getData();
        JSONObject jsonObject = (JSONObject) JSON.parse(result);
        String code = jsonObject.getString("code");
        if ("00000".equals(code)) {
            Object object = jsonObject.get("data");
            List<Map<String, String>> respList = null;
            if (object instanceof List) {
                respList = (List<Map<String, String>>) object;
            } else if (object instanceof Map) {
                respList = new ArrayList<>();
                respList.add((Map<String, String>) object);
            }
            if (CollUtil.isNotEmpty(respList)) {
                updateInvoiceUrl(respList.get(0), seriano);
            }
        }
    }

    /**
     * 更新发票pdfUrl
     *
     * @param map
     * @param seriano
     */
    public void updateInvoiceUrl(Map<String, String> map, String seriano) {
        SellerInvoiceEntity sellerInvoiceEntity = new SellerInvoiceEntity();
        sellerInvoiceEntity.setInvoiceUrl(map.get("url"));
        UpdateWrapper<SellerInvoiceEntity> updateWrapper = new UpdateWrapper();
        updateWrapper.in("serial_no", seriano);
        this.update(sellerInvoiceEntity, updateWrapper);
    }
}
